module Syntax where

import Text.Megaparsec
import Text.Megaparsec.Char
import Data.Void (Void)

data Pipeline = Command CmdName [CmdWord]
              | ToFile Pipeline FilePath
              | Pipe Pipeline Pipeline
              deriving Show

newtype CmdName = CmdName { getCmdName :: String
                          } deriving Show
newtype CmdWord = CmdWord { getCmdWord :: String
                          } deriving Show

wordP :: Parsec Void String String
wordP = some $ noneOf " |<>"

cmdNameP :: Parsec Void String CmdName
cmdNameP = CmdName <$> wordP

cmdWordP :: Parsec Void String CmdWord
cmdWordP = CmdWord <$> wordP

commandP :: Parsec Void String Pipeline
commandP = Command <$> cmdNameP <* space <*> sepEndBy cmdWordP space

toFileP :: Parsec Void String Pipeline
toFileP = ToFile <$> commandP <*> (char '>' *> space *> wordP)

pipeP :: Parsec Void String Pipeline
pipeP = Pipe <$> commandP <*> (char '|' *> space *> pipelineP)

pipelineP :: Parsec Void String Pipeline
pipelineP =
  space *>
  choice [ try toFileP
         , try pipeP
         , try commandP]
  <* space
